package com.lemon.exam.common.converter;

import com.lemon.exam.entity.vo.MenuVO;
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.lang.NonNull;

import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 用户ID元组对象转换
 *
 * @author Lemon
 * @since 2025/5/4 15:48
 */
@ReadingConverter
public class MenuConverter implements Converter<Row, MenuVO> {
    /**
     * 映射关系
     * 字段 -> 字段类型 -> 字段赋值方法
     */
    private static final Function<MenuVO, List<Triple<String, Class<?>, Consumer<Object>>>> MAPPING = entity -> List.of(
            Triple.of("id", Long.class, v -> entity.setId((Long) v)),
            Triple.of("path", String.class, v -> entity.setPath((String) v)),
            Triple.of("parent_id", Long.class, v -> entity.setParentId((Long) v)),
            Triple.of("name", String.class, v -> entity.setName((String) v)),
            Triple.of("icon", String.class, v -> entity.setIcon((String) v)),
            Triple.of("seq", Integer.class, v -> entity.setSeq((Integer) v)),
            Triple.of("tree_link_id", String.class, v -> entity.setTreeLinkId((String) v)),
            Triple.of("create_by", String.class, v -> entity.setCreateBy((String) v)),
            Triple.of("create_time", LocalDateTime.class, v -> entity.setCreateTime((LocalDateTime) v)),
            Triple.of("update_by", String.class, v -> entity.setUpdateBy((String) v)),
            Triple.of("update_time", LocalDateTime.class, v -> entity.setUpdateTime((LocalDateTime) v)),
            Triple.of("status", Integer.class, v -> entity.setStatus((Integer) v))
    );

    @Override
    @NonNull
    public MenuVO convert(Row source) {
        RowMetadata meta = source.getMetadata();
        MenuVO entity = new MenuVO();
        MAPPING.apply(entity).forEach(mapping -> {
            if (meta.contains(mapping.getLeft())) {
                mapping.getRight().accept(source.get(mapping.getLeft(), mapping.getMiddle()));
            }
        });
        return entity;
    }
}
